﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TireService.Data;
using System.Web.Security;
using System.Configuration;
using System.Collections;

namespace TireService.Web.Finance
{
    public partial class InvoiceList : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            // Register export button as full postback - otherwise it wount work because it is inside a update panel
            ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
            scriptManager.RegisterPostBackControl(this.btnExport.FindControl("btnExport"));
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            if (Page.IsPostBack != true)
            {
                // Set client side validation for actions
                btnSubmitAction.Attributes["OnClick"] = "return confirm_submit(" + ddlAction.ClientID + ");";

                // Bind filter data
                ListItem liFilter = new ListItem();
                liFilter.Value = "0";
                liFilter.Text = "Vis alle";
                ddlFilter.Items.Add(liFilter);
                ddlFilter.DataSource = db.GetInvoiceStatus();
                ddlFilter.DataValueField = "InvoiceStatusId";
                ddlFilter.DataTextField = "Description";
                ddlFilter.DataBind();
            }

            BindInvoiceData(db, Convert.ToInt32(ddlFilter.SelectedValue));
        }


        #region Private Functions

        /// <summary>
        /// Function that bind invoice data to gridview
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="InvoiceStatusId">Id on orderstatus to database</param>
        protected void BindInvoiceData(TireServiceDB db, int InvoiceStatusId)
        {
            if (InvoiceStatusId == 0)
            {
                gvInvoice.DataSource = db.GetInvoices();
            }
            else
            {
                gvInvoice.DataSource = db.GetInvoices(InvoiceStatusId);
            }

            gvInvoice.DataBind();
        }

        /// <summary>
        /// Function that runs specific action
        /// </summary>
        /// <param name="Action">Id for action to run</param>
        protected void SubmitAction(int Action)
        {
            if (Action == 0)
            {
                throw new ArgumentException("Ingen handling valgt.");
            }
            if (Action == 1)
            {
                // Edit selected invoices
                EditSelectedInvoice();
            }
            
            if (Action == 4)
            {
                // Change selected invoices to paid status and send confirmation email to customer
                MarkSelectedInvoicesAsPaid(true);
            }
            if (Action == 5)
            {
                // Change selected invoices to paid status and do NOT send confirmation email to customer
                MarkSelectedInvoicesAsPaid(false);
            }
            if (Action == 6)
            {
                // Email selected invoices to customers
                EmailSelectedInvoices();
            }
            if (Action == 7)
            {
                // Email reminder for selected invoices to customers
                EmailReminderForSelectedInvoices();
            }

        }

        private void EmailReminderForSelectedInvoices()
        {
            List<object> keyValues = gvInvoice.GetSelectedFieldValues("InvoiceId");

            if (keyValues.Count != 0)
            {
                TireServiceDB db = new TireServiceDB();

                // Change invoice status to paid for selected invoices
                foreach (object key in keyValues)
                {
                    // Fetch invoice
                    Invoice invoice = db.GetInvoice(Convert.ToInt32(key.ToString()));

                    if (invoice != null)
                    {
                        // Update invoice
                        if (invoice.InvoiceStatusId != (int)Shared.InvoiceStatus.Paid & invoice.InvoiceStatusId != (int)Shared.InvoiceStatus.Cancelled)
                        {
                            // Get all invoicedetails
                            List<InvoiceDetail> details = invoice.InvoiceDetails.Where(p => p.CustomerSubscriptionId != null).ToList();

                            // Declare system userid
                            Guid userid = new Guid(Membership.GetUser().ProviderUserKey.ToString());

                            //int subscriptionid = 0;

                            // Update each customer subscription as paid
                            foreach (InvoiceDetail detail in details)
                            {
                                if (detail.CustomerSubscriptionId != null)
                                {
                                    // Update subscription as paid
                                    CustomerSubscription subscription = db.GetCustomerSubscription(Convert.ToInt32(detail.CustomerSubscriptionId));

                                    //subscriptionid = subscription.SubscriptionId;

                                    // Create log on reminder
                                    CustomerSubscriptionLogBLL subscriptionBLL = new CustomerSubscriptionLogBLL();
                                    subscriptionBLL.CreateCustomerSubscriptionLog(db, subscription, (int)Shared.SubscriptionLogAction.Paid, userid, "Betalings reminder sendt");
                                }
                            }

                            // Fetch customer
                            Customer customer = db.GetCustomer(invoice.CustomerId);

                            // Send email to customer
                            SendReminderOnInvoiceEmail(customer.Email, customer.Name, invoice.InvoiceGuid.ToString(), invoice.InvoiceId.ToString());
                        }                        
                    }
                }

                // Update message
                lMessage.Text = "Betalingspåmindelse sendt til kunder for valgte fakturaer.";
            }
            else
            {
                throw new ArgumentException("Ingen fakturaer valgt.");
            }
        }

        private void EmailSelectedInvoices()
        {
            List<object> keyValues = gvInvoice.GetSelectedFieldValues("InvoiceId");

            if (keyValues.Count != 0)
            {
                TireServiceDB db = new TireServiceDB();

                // Change invoice status to paid for selected invoices
                foreach (object key in keyValues)
                {
                    // Fetch invoice
                    Invoice invoice = db.GetInvoice(Convert.ToInt32(key.ToString()));

                    if (invoice != null)
                    {
                        // Update invoice
                        if (invoice.InvoiceStatusId != (int)Shared.InvoiceStatus.Paid & invoice.InvoiceStatusId != (int)Shared.InvoiceStatus.Cancelled)
                        {
                            // Get all invoicedetails
                            List<InvoiceDetail> details = invoice.InvoiceDetails.Where(p => p.SubscriptionId != null & p.CustomerId != null).ToList();

                            // Declare system userid
                            Guid userid = new Guid(Membership.GetUser().ProviderUserKey.ToString());

                            // Update each customer subscription as paid
                            foreach (InvoiceDetail detail in details)
                            {
                                if (detail.SubscriptionId != null)
                                {
                                    // Update subscription as paid
                                    CustomerSubscription subscription = db.GetCustomerSubscription(Convert.ToInt32(detail.CustomerSubscriptionId));

                                    // Create log on email send
                                    CustomerSubscriptionLogBLL subscriptionBLL = new CustomerSubscriptionLogBLL();
                                    subscriptionBLL.CreateCustomerSubscriptionLog(db, subscription, (int)Shared.SubscriptionLogAction.Paid, userid, "Faktura sendt pr. email");
                                }
                            }

                            // Fetch customer
                            Customer customer = db.GetCustomer(invoice.CustomerId);

                            // Send email to customer
                            SendInvoiceEmail(customer.Email, customer.Name, invoice.InvoiceGuid.ToString(), invoice.InvoiceId.ToString());
                        }
                    }
                }

                // Update message
                lMessage.Text = "Valgte fakturaer sendt til kunder.";
            }
            else
            {
                throw new ArgumentException("Ingen fakturaer valgt.");
            }
        }

        private void EditSelectedInvoice()
        {
            throw new ArgumentException("Funktion ikke implementeret endnu.");
        }

        ///// <summary>
        ///// Function that change status on invoice
        ///// </summary>
        ///// <param name="db">Connection to database</param>
        ///// <param name="InvoiceId">Id on invoice to change status on</param>
        ///// <param name="InvoiceStatus">New status on invoice</param>
        //protected void ChangeInvoiceStatus(TireServiceDB db, int InvoiceId, Shared.InvoiceStatus InvoiceStatus)
        //{
        //    Invoice invoice = db.GetInvoice(InvoiceId);

        //    // Check that invoice status is different for current invoice status
        //    if (invoice.InvoiceStatusId != (int)InvoiceStatus)
        //    {
        //        // Invoice status changed to invoiced, reminder or reminder fee one
        //        if (InvoiceStatus == Shared.InvoiceStatus.Invoiced | InvoiceStatus == Shared.InvoiceStatus.Reminder | InvoiceStatus == Shared.InvoiceStatus.ReminderFeeOne)
        //        {
        //            if (invoice.InvoiceStatusId == (int)Shared.InvoiceStatus.Paid)
        //            {
        //                // Invoice was already set as paid - change order status for all orders related to invoicedetails
        //                List<InvoiceDetail> invoicedetails = db.GetInvoiceDetails(invoice.InvoiceId);
        //                foreach (InvoiceDetail invoicedetail in invoicedetails)
        //                {
        //                    // Get order
        //                    if (invoicedetail.OrderId != null)
        //                    {
        //                        // Update order status to invoiced
        //                        Order order = db.GetOrder(Convert.ToInt32(invoicedetail.OrderId));
        //                        int oldstatus = order.OrderStatusId;
        //                        order.OrderStatusId = (int)Shared.OrderStatus.Invoiced;

        //                        // Create orderstatushistory record
        //                        OrderStatusHistory orderstatushistory = new OrderStatusHistory();
        //                        orderstatushistory.OrderId = Convert.ToInt32(invoicedetail.OrderId);
        //                        orderstatushistory.OrderStatusId = (int)Shared.OrderStatus.Invoiced;
        //                        orderstatushistory.FromOrderStatusId = oldstatus;
        //                        orderstatushistory.Date = DateTime.Now;
        //                        orderstatushistory.UserId = new Guid(Membership.GetUser().ProviderUserKey.ToString());

        //                        db.AddOrderStatusHistory(orderstatushistory);
        //                    }
        //                }
        //            }
        //        }

        //        // Invoice status changed to paid
        //        if (InvoiceStatus == Shared.InvoiceStatus.Paid)
        //        {
        //            // Change order status to paid for each invoicedetail
        //            List<InvoiceDetail> invoicedetails = db.GetInvoiceDetails(invoice.InvoiceId);
        //            foreach (InvoiceDetail invoicedetail in invoicedetails)
        //            {
        //                // Get order
        //                if (invoicedetail.OrderId != null)
        //                {
        //                    // Update order status to paid
        //                    Order order = db.GetOrder(Convert.ToInt32(invoicedetail.OrderId));
        //                    int oldstatus = order.OrderStatusId;
        //                    order.OrderStatusId = (int)Shared.OrderStatus.PaidClosed;

        //                    // Create orderstatushistory record
        //                    OrderStatusHistory orderstatushistory = new OrderStatusHistory();
        //                    orderstatushistory.OrderId = Convert.ToInt32(invoicedetail.OrderId);
        //                    orderstatushistory.OrderStatusId = (int)Shared.OrderStatus.PaidClosed;
        //                    orderstatushistory.FromOrderStatusId = oldstatus;
        //                    orderstatushistory.Date = DateTime.Now;
        //                    orderstatushistory.UserId = new Guid(Membership.GetUser().ProviderUserKey.ToString());

        //                    db.AddOrderStatusHistory(orderstatushistory);
        //                }
        //            }
        //        }

        //        invoice.InvoiceStatusId = (int)InvoiceStatus;
        //    }
        //}

        /// <summary>
        /// Function that runs through all selected invoices in gridview and change their status to paid
        /// </summary>
        /// <param name="SendEmail">True/false value indicating if email should be send to customer afterwards</param>
        protected void MarkSelectedInvoicesAsPaid(bool SendCustomerEmail)
        {
            List<object> keyValues = gvInvoice.GetSelectedFieldValues("InvoiceId");

            if (keyValues.Count != 0)
            {
                TireServiceDB db = new TireServiceDB();

                // Change invoice status to paid for selected invoices
                foreach (object key in keyValues)
                {
                    // Fetch invoice
                    Invoice invoice = db.GetInvoice(Convert.ToInt32(key.ToString()));

                    if (invoice != null)
                    {
                        // Update invoice
                        invoice.InvoiceStatusId = (int)Shared.InvoiceStatus.Paid;

                        // Get all invoicedetails
                        List<InvoiceDetail> details = invoice.InvoiceDetails.Where(p => p.CustomerSubscriptionId != null).ToList();

                        // Declare system userid
                        Guid userid = new Guid(Membership.GetUser().ProviderUserKey.ToString());

                        int subscriptionid = 0;
                        int customersubscriptionid = 0;

                        // Fetch customer
                        Customer customer = db.GetCustomer(invoice.CustomerId);                            

                        // Update each customer subscription as paid
                        foreach (InvoiceDetail detail in details)
                        {
                            if (detail.SubscriptionId != null)
                            {
                                // Update subscription as paid
                                CustomerSubscription subscription = db.GetCustomerSubscription(Convert.ToInt32(detail.CustomerSubscriptionId));
                                subscription.Paid = true;

                                subscriptionid = subscription.SubscriptionId;
                                customersubscriptionid = subscription.CustomerSubscriptionId;

                                // TODO: Find car and change status
                                //Car car = db.GetCars()

                                // Create log on payment
                                CustomerSubscriptionLogBLL subscriptionBLL = new CustomerSubscriptionLogBLL();
                                subscriptionBLL.CreateCustomerSubscriptionLog(db, subscription, (int)Shared.SubscriptionLogAction.Paid, userid, "Bankoverførsel betaling");

                                // Send mail with confirmation on paid subscription
                                SendEmailSubscriptionPaid(customer.Email, customer.Name, customer.CustomerId.ToString(), subscriptionid.ToString(), customersubscriptionid.ToString());
                            }
                        }

                        // Commit changes to database
                        db.SubmitChanges();

                        if (SendCustomerEmail)
                        {
                            // Send overall confirmation on paid invoice
                            //SendEmail(customer.Email, customer.Name, customer.CustomerId.ToString(), subscriptionid.ToString(), invoice.InvoiceGuid.ToString(), customersubscriptionid.ToString(), invoice.InvoiceId);
                            SendEmail(customer.Email, customer.Name, invoice.InvoiceGuid.ToString(), invoice.InvoiceId);
                        }                       
                    }
                }

                // Refresh gridview
                BindInvoiceData(db, Convert.ToInt32(ddlFilter.SelectedValue));

                // Dispose database connection
                db.Dispose();

                // Show message
                if (SendCustomerEmail)
                {
                    lMessage.Text = "Valgte fakturaer angivet som betalt og email bekræftelse sendt til kunder.";
                }
                else
                {
                    lMessage.Text = "Valgte fakturaer angivet som betalt.";
                }
                
            }
            else
            {
                throw new ArgumentException("Ingen fakturaer valgt.");
            }
        }

        /// <summary>
        /// Function that sends email to customer confirmation on payment for specific customer subscription
        /// </summary>
        /// <param name="CustomerEmail">Customer email that this email will be send to</param>
        /// <param name="CustomerName">Name on customer</param>
        /// <param name="CustomerId">Id on customer</param>
        /// <param name="SubscriptionId">Id on subscription</param>
        /// <param name="CustomerSubscriptionId">Unik customer subscription id</param>
        private void SendEmailSubscriptionPaid(string CustomerEmail, string CustomerName, string CustomerId, string SubscriptionId, string CustomerSubscriptionId)
        {
            string Subject = "Abonnement: " + CustomerId + "-" + SubscriptionId + "-" + CustomerSubscriptionId + " betalt";
            bool test = Convert.ToBoolean(Convert.ToByte(ConfigurationManager.AppSettings["TestEnvironmentOn"]));
            Shared email = new Shared();

            Hashtable templateVars = new Hashtable();

            // Send email to customer
            templateVars.Add("CustomerName", CustomerName);
            templateVars.Add("CustomerId", CustomerId);
            templateVars.Add("SubscriptionId", SubscriptionId);
            templateVars.Add("CustomerSubscriptionId", CustomerSubscriptionId);
            Shared.Parser parser = new Shared.Parser(Server.MapPath("~/Reports/HtmlTemplates/BetalingAbonnement.htm"), templateVars);

            // Send email to customer with us on bcc
            email.SendEmail(CustomerEmail, ConfigurationManager.AppSettings["EmailAddress"].ToString(), parser.Parse(), Subject, true, test, ConfigurationManager.AppSettings["EmailAddress"].ToString(), null, null);
        }

        /// <summary>
        /// Function that sends email to customer confirmation on paid invoice
        /// </summary>
        /// <param name="CustomerEmail">Customer email that this email will be send to</param>
        /// <param name="CustomerName">Name on customer</param>
        /// <param name="InvoiceGuid">Unik Guid number for invoice</param>
        /// <param name="InvoiceId">Id on Invoice</param>
        private void SendEmail(string CustomerEmail, string CustomerName, string InvoiceGuid, int InvoiceId)
        {
            string Subject = "Betaling gennemført - Faktura " + InvoiceId.ToString();
            bool test = Convert.ToBoolean(Convert.ToByte(ConfigurationManager.AppSettings["TestEnvironmentOn"]));
            Shared email = new Shared();

            Hashtable templateVars = new Hashtable();

            // Send email to customer
            templateVars.Add("CustomerName", CustomerName);
            templateVars.Add("InvoiceGuid", InvoiceGuid);
            templateVars.Add("InvoiceId", InvoiceId);
            Shared.Parser parser = new Shared.Parser(Server.MapPath("~/Reports/HtmlTemplates/Betaling.htm"), templateVars);

            // Send email to customer with us on bcc
            email.SendEmail(CustomerEmail, ConfigurationManager.AppSettings["EmailAddress"].ToString(), parser.Parse(), Subject, true, test, ConfigurationManager.AppSettings["EmailAddress"].ToString(), null, null);
        }

        /// <summary>
        /// Function that sends email to customer with invoice
        /// </summary>
        /// <param name="CustomerEmail">Customer email that this email will be send to</param>
        /// <param name="CustomerName">Name on customer</param>
        /// <param name="InvoiceId">Id on Invoice</param>
        /// <param name="InvoiceGuid">Unik Guid number for invoice</param>
        private void SendInvoiceEmail(string CustomerEmail, string CustomerName, string InvoiceGuid, string InvoiceId)
        {
            string Subject = "Faktura " + InvoiceId;
            bool test = Convert.ToBoolean(Convert.ToByte(ConfigurationManager.AppSettings["TestEnvironmentOn"]));
            Shared email = new Shared();

            Hashtable templateVars = new Hashtable();

            // Send email to customer
            templateVars.Add("CustomerName", CustomerName);
            templateVars.Add("InvoiceGuid", InvoiceGuid);
            templateVars.Add("InvoiceId", InvoiceId);
            Shared.Parser parser = new Shared.Parser(Server.MapPath("~/Reports/HtmlTemplates/Invoice.htm"), templateVars);

            // Send email to customer with us on bcc
            email.SendEmail(CustomerEmail, ConfigurationManager.AppSettings["EmailAddress"].ToString(), parser.Parse(), Subject, true, test, ConfigurationManager.AppSettings["EmailAddress"].ToString(), null, null);
        }

        /// <summary>
        /// Function that sends email to customer with reminder on invoice payment
        /// </summary>
        /// <param name="CustomerEmail">Customer email that this email will be send to</param>
        /// <param name="CustomerName">Name on customer</param>
        /// <param name="InvoiceGuid">Unik Guid number for invoice</param>
        /// <param name="InvoiceId">Id on Invoice</param>
        private void SendReminderOnInvoiceEmail(string CustomerEmail, string CustomerName, string InvoiceGuid, string InvoiceId)
        {
            string Subject = "Manglende betaling - faktura " + InvoiceId;
            bool test = Convert.ToBoolean(Convert.ToByte(ConfigurationManager.AppSettings["TestEnvironmentOn"]));
            Shared email = new Shared();

            Hashtable templateVars = new Hashtable();

            // Send email to customer
            templateVars.Add("CustomerName", CustomerName);
            templateVars.Add("InvoiceGuid", InvoiceGuid);
            templateVars.Add("InvoiceId", InvoiceId);
            Shared.Parser parser = new Shared.Parser(Server.MapPath("~/Reports/HtmlTemplates/ReminderOnPayment.htm"), templateVars);

            // Send email to customer with us on bcc
            email.SendEmail(CustomerEmail, ConfigurationManager.AppSettings["EmailAddress"].ToString(), parser.Parse(), Subject, true, test, ConfigurationManager.AppSettings["EmailAddress"].ToString(), null, null);
        }

        #endregion

        #region Control Functions

        /// <summary>
        /// Button function for export of gridview
        /// </summary>
        protected void btnExport_Click(object sender, EventArgs e)
        {
            if (ddlExport.SelectedValue == "0")
            {
                gvExport.WritePdfToResponse();
            }

            if (ddlExport.SelectedValue == "1")
            {
                gvExport.WriteXlsToResponse();
            }

            if (ddlExport.SelectedValue == "2")
            {
                gvExport.WriteCsvToResponse();
            }

            if (ddlExport.SelectedValue == "3")
            {
                gvExport.WriteRtfToResponse();
            }
        }

        /// <summary>
        /// Button function that submit selected action in action dropdownlist
        /// </summary>
        protected void btnSubmitAction_Click(object sender, EventArgs e)
        {
            try
            {
                SubmitAction(Convert.ToInt32(ddlAction.SelectedValue));
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        #endregion

        #region GridView Events

        /// <summary>
        /// Gridview function that change field data for unbound fields
        /// </summary>
        protected void gvInvoice_CustomUnboundColumnData(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewColumnDataEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            // Format UnBoundColumn OrderStatusDescription: Show order status
            if (e.Column.FieldName == "InvoiceStatusDescription")
            {
                // Get invoicestatusid
                int invoicestatusid = Convert.ToInt32(e.GetListSourceFieldValue("InvoiceStatusId"));

                // Change field value
                e.Value = db.GetInvoiceStatusDescription(invoicestatusid);
            }
        }

        /// <summary>
        /// Gridview function that handles edit selection of invoices
        /// </summary>
        protected void gvInvoice_CustomButtonCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomButtonCallbackEventArgs e)
        {
            try
            {
                if (e.ButtonID == "Edit")
                {
                    // Get invoiceid
                    int invoiceid = Convert.ToInt32(gvInvoice.GetRowValues(e.VisibleIndex, "InvoiceGuid"));

                    Response.Redirect("EditInvoice.aspx?InvoiceGuid=" + invoiceid.ToString());
                }
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Gridview function that runs when user has confirmed to delete invoice 
        /// </summary>
        protected void gvInvoice_RowDeleting(object sender, DevExpress.Web.Data.ASPxDataDeletingEventArgs e)
        {
            // Delete order
            try
            {
                //e.Cancel = true;

                //// Instantiate datalayer
                //AutoimageDB db = new AutoimageDB();

                //// Delete order
                //DeleteOrder(db, Convert.ToInt32(e.Keys[0]));

                //// Refresh gridview with orders
                //BindOrderData(db, Convert.ToInt32(ddlFilter.SelectedValue));

                //// Change message
                lMessage.Text = "Ikke implementeret endnu";
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        #endregion
    }
}